home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 3 / Cream of the Crop 3.iso / utility / mu17_ext.zip / ACCOUNTS.C < prev    next >
C/C++ Source or Header  |  1994-03-07  |  21KB  |  885 lines

  1. /*
  2. **    $VER: accounts.c 1.2 (07.02.94)
  3. **
  4. **    accounts.library functions
  5. **
  6. **    ⌐ Copyright 1994 by Norbert Pⁿschel
  7. **    All Rights Reserved
  8. */
  9.  
  10. #include <proto/exec.h>
  11. #include <proto/dos.h>
  12. #include <proto/multiuser.h>
  13. #include <clib/accounts_protos.h>
  14. #include <pragmas/accounts_pragmas.h>
  15. #include <clib/alib_protos.h>
  16.  
  17. #include <exec/memory.h>
  18. #include <exec/alerts.h>
  19. #include <dos/notify.h>
  20. #include <envoy/errors.h>
  21.  
  22. #include <string.h>
  23.  
  24. #include <debug.h>
  25.  
  26. #define NOBODY
  27.  
  28. #ifdef NOBODY
  29. const UBYTE nobody[] = "nobody";
  30.  
  31. #define NOBODYNAME (STRPTR)nobody
  32. #endif
  33.  
  34. #define BUFFLEN 256
  35. #define UNAMELEN 32
  36. #define GNAMELEN 32
  37. #define PWDLEN   16
  38.  
  39. extern struct Library *AccountsBase;
  40.  
  41. /* accounts.library guardian process */
  42.  
  43. extern volatile struct Process *guardian;
  44.  
  45. struct MinList         UserList;
  46. struct SignalSemaphore UserSemaphore;
  47. struct MinList         GroupList;
  48. struct SignalSemaphore GroupSemaphore;
  49.  
  50. struct InternalUserInfo {
  51.   struct MinNode  iui_Node;
  52.   struct UserInfo iui_UserInfo;
  53.   struct MinList  iui_SecGroups;
  54.   UBYTE           iui_CryptPasswd[PWDLEN];
  55. };
  56.  
  57. struct InternalGroupInfo {
  58.   struct MinNode   igi_Node;
  59.   struct GroupInfo igi_GroupInfo;
  60. };
  61.  
  62. struct SecGroup {
  63.   struct MinNode            sg_Node;
  64.   struct InternalGroupInfo *sg_IGI;
  65. };
  66.  
  67. void init_users(void)
  68.  
  69. {
  70.   NewList((struct List *)&UserList);
  71.   memset(&UserSemaphore,0,sizeof(struct SignalSemaphore));
  72.   InitSemaphore(&UserSemaphore);
  73. }
  74.  
  75. void init_groups(void)
  76.  
  77. {
  78.   NewList((struct List *)&GroupList);
  79.   memset(&GroupSemaphore,0,sizeof(struct SignalSemaphore));
  80.   InitSemaphore(&GroupSemaphore);
  81. }
  82.  
  83. void free_users(void)
  84.  
  85. {
  86.   struct InternalUserInfo *iui;
  87.   struct SecGroup *sg;
  88.  
  89.   ObtainSemaphore(&UserSemaphore);
  90.   iui = (struct InternalUserInfo *)(UserList.mlh_Head);  
  91.   while(iui->iui_Node.mln_Succ) {
  92.     Remove((struct Node *)iui);
  93.     sg = (struct SecGroup *)(iui->iui_SecGroups.mlh_Head);
  94.     while(sg->sg_Node.mln_Succ) {
  95.       Remove((struct Node *)sg);
  96.       FreeMem(sg,sizeof(struct SecGroup));
  97.       sg = (struct SecGroup *)(iui->iui_SecGroups.mlh_Head);
  98.     }
  99.     FreeMem(iui,sizeof(struct InternalUserInfo));
  100.     iui = (struct InternalUserInfo *)(UserList.mlh_Head);  
  101.   }
  102.   ReleaseSemaphore(&UserSemaphore);  
  103. }
  104.  
  105. void free_groups(void)
  106.  
  107. {
  108.   struct InternalGroupInfo *igi;
  109.  
  110.   ObtainSemaphore(&GroupSemaphore);
  111.   igi = (struct InternalGroupInfo *)(GroupList.mlh_Head);  
  112.   while(igi->igi_Node.mln_Succ) {
  113.     Remove((struct Node *)igi);
  114.     FreeMem(igi,sizeof(struct InternalGroupInfo));
  115.     igi = (struct InternalGroupInfo *)(GroupList.mlh_Head);  
  116.   }
  117.   ReleaseSemaphore(&GroupSemaphore);  
  118. }
  119.  
  120. BOOL adduser(STRPTR uname,UWORD uid,UWORD gid,ULONG flags,STRPTR pwd)
  121.  
  122. {
  123.   struct InternalUserInfo *iui;
  124.  
  125.   iui = (struct InternalUserInfo *)
  126.         AllocMem(sizeof(struct InternalUserInfo),MEMF_PUBLIC);
  127.   if(iui) {
  128.     strncpy(iui->iui_UserInfo.ui_UserName,uname,UNAMELEN);
  129.     iui->iui_UserInfo.ui_UserID = uid;
  130.     iui->iui_UserInfo.ui_PrimaryGroupID = gid;
  131.     iui->iui_UserInfo.ui_Flags = flags;
  132.     strncpy(iui->iui_CryptPasswd,pwd,PWDLEN);
  133.     NewList((struct List *)&(iui->iui_SecGroups));
  134.     AddTail((struct List *)&UserList,(struct Node *)iui);
  135.   }
  136.   return((BOOL)(iui != 0));
  137. }
  138.  
  139. BOOL addgroup(STRPTR gname,UWORD gid)
  140.  
  141. {
  142.   struct InternalGroupInfo *igi;
  143.  
  144.   igi = (struct InternalGroupInfo *)
  145.         AllocMem(sizeof(struct InternalGroupInfo),MEMF_PUBLIC);
  146.   if(igi) {
  147.     strncpy(igi->igi_GroupInfo.gi_GroupName,gname,32);
  148.     igi->igi_GroupInfo.gi_GroupID = gid;
  149.     AddTail((struct List *)&GroupList,(struct Node *)igi);
  150.   }
  151.   return((BOOL)(igi != 0));
  152. }
  153.  
  154. BOOL addsecgroup(struct InternalUserInfo *iui,struct InternalGroupInfo *igi)
  155.  
  156. {
  157.   struct SecGroup *sg;
  158.  
  159.   sg = (struct SecGroup *)AllocMem(sizeof(struct SecGroup),MEMF_PUBLIC);
  160.   if(sg) {
  161.     sg->sg_IGI = igi;
  162.     AddTail((struct List *)&(iui->iui_SecGroups),(struct Node *)sg);
  163.   }
  164.   return((BOOL)(sg != 0));
  165. }
  166.  
  167. STRPTR nextsep(STRPTR s,UBYTE sep)
  168.  
  169. {
  170.   while(*s && *s != '\n' && *s != sep) s++;
  171.   return(s);
  172. }
  173.  
  174. struct InternalUserInfo *finduid(UWORD uid)
  175.  
  176. {
  177.   struct InternalUserInfo *iui;
  178.  
  179.   iui = (struct InternalUserInfo *)(UserList.mlh_Head);  
  180.   while(iui->iui_Node.mln_Succ) {
  181.     if(iui->iui_UserInfo.ui_UserID == uid) return(iui);
  182.     iui = (struct InternalUserInfo *)(iui->iui_Node.mln_Succ);  
  183.   }
  184.   return(0);
  185. }
  186.  
  187. struct InternalGroupInfo *findgid(UWORD gid)
  188.  
  189. {
  190.   struct InternalGroupInfo *igi;
  191.  
  192.   igi = (struct InternalGroupInfo *)(GroupList.mlh_Head);  
  193.   while(igi->igi_Node.mln_Succ) {
  194.     if(igi->igi_GroupInfo.gi_GroupID == gid) return(igi);
  195.     igi = (struct InternalGroupInfo *)(igi->igi_Node.mln_Succ);  
  196.   }
  197.   return(0);
  198. }
  199.  
  200. struct InternalUserInfo *finduname(STRPTR uname)
  201.  
  202. {
  203.   struct InternalUserInfo *iui;
  204.  
  205.   iui = (struct InternalUserInfo *)(UserList.mlh_Head);  
  206.   while(iui->iui_Node.mln_Succ) {
  207.     if(strcmp(iui->iui_UserInfo.ui_UserName,uname) == 0) return(iui);
  208.     iui = (struct InternalUserInfo *)(iui->iui_Node.mln_Succ);  
  209.   }
  210.   return(0);
  211. }
  212.  
  213. struct InternalGroupInfo *findgname(STRPTR gname)
  214.  
  215. {
  216.   struct InternalGroupInfo *igi;
  217.  
  218.   igi = (struct InternalGroupInfo *)(GroupList.mlh_Head);  
  219.   while(igi->igi_Node.mln_Succ) {
  220.     if(strcmp(igi->igi_GroupInfo.gi_GroupName,gname) == 0) return(igi);
  221.     igi = (struct InternalGroupInfo *)(igi->igi_Node.mln_Succ);  
  222.   }
  223.   return(0);
  224. }
  225.  
  226. struct InternalUserInfo *finduser(STRPTR uname,UWORD uid)
  227.  
  228. {
  229.   struct InternalUserInfo *iui;
  230.  
  231.   iui = (struct InternalUserInfo *)(UserList.mlh_Head);  
  232.   while(iui->iui_Node.mln_Succ) {
  233.     if(iui->iui_UserInfo.ui_UserID == uid &&
  234.        strcmp(iui->iui_UserInfo.ui_UserName,uname) == 0) return(iui);
  235.     iui = (struct InternalUserInfo *)(iui->iui_Node.mln_Succ);  
  236.   }
  237.   return(0);
  238. }
  239.  
  240. struct InternalGroupInfo *findgroup(STRPTR gname,UWORD gid)
  241.  
  242. {
  243.   struct InternalGroupInfo *igi;
  244.  
  245.   igi = (struct InternalGroupInfo *)(GroupList.mlh_Head);  
  246.   while(igi->igi_Node.mln_Succ) {
  247.     if(igi->igi_GroupInfo.gi_GroupID == gid &&
  248.       strcmp(igi->igi_GroupInfo.gi_GroupName,gname) == 0) return(igi);
  249.     igi = (struct InternalGroupInfo *)(igi->igi_Node.mln_Succ);  
  250.   }
  251.   return(0);
  252. }
  253.  
  254. BOOL issecmem(struct InternalUserInfo *iui,struct InternalGroupInfo *igi)
  255.  
  256. {
  257.   struct SecGroup *sg;
  258.  
  259.   sg = (struct SecGroup *)(iui->iui_SecGroups.mlh_Head);
  260.   while(sg->sg_Node.mln_Succ) {
  261.     if(sg->sg_IGI == igi) return(TRUE);
  262.     sg = (struct SecGroup *)(sg->sg_Node.mln_Succ);
  263.   }
  264.   return(FALSE);
  265. }
  266.  
  267. void read_users(void)
  268.  
  269. {
  270.   BPTR passwd;
  271.   UBYTE buff[BUFFLEN];
  272.   STRPTR s,pwd,uidstr,gidstr;
  273.   ULONG flags = 0;
  274.   LONG uid,gid;
  275.  
  276.   ObtainSemaphore(&UserSemaphore);
  277.  
  278. #ifdef NOBODY
  279.   if(!adduser(NOBODYNAME,0,0,0,"")) return;
  280. #endif
  281.  
  282.   passwd = Open(muPasswd_FileName,MODE_OLDFILE);
  283.   if(passwd) {
  284.     while(FGets(passwd,buff,BUFFLEN-1)) {
  285.       s = nextsep(buff,'|');
  286.       if(*s != '|') break;
  287.       *(s++) = '\0';
  288.       pwd = s;
  289.       s = nextsep(pwd,'|');
  290.       if(*s != '|') break;
  291.       if(s != pwd) flags = UFLAGF_NeedsPassword;
  292.       *(s++) = '\0';
  293.       uidstr = s;
  294.       s = nextsep(uidstr,'|');
  295.       if(*s != '|') break;
  296.       *(s++) = '\0';
  297.       gidstr = s;
  298.       s = nextsep(gidstr,'|');
  299.       if(*s != '|') break;
  300.       *s = '\0';
  301.  
  302.       if(StrToLong(uidstr,&uid) <= 0) break;
  303.       if(StrToLong(gidstr,&gid) <= 0) break;
  304.  
  305.       flags |= UFLAGF_AdminPassword; /* should evaluate config !!! */
  306.       if(uid == muROOT_UID) flags |= (UFLAGF_AdminGroups|UFLAGF_AdminAll);
  307.  
  308.       if(!adduser(buff,uid,gid,flags,pwd)) break;
  309.     }
  310.     Close(passwd);
  311.   }
  312.   ReleaseSemaphore(&UserSemaphore);
  313. }
  314.  
  315. void read_groups(void)
  316.  
  317. {
  318.   BPTR group;
  319.   UBYTE buff[BUFFLEN];
  320.   STRPTR s,uidstr,gidstr;
  321.   LONG uid,gid;
  322.   struct InternalGroupInfo *igi;
  323.   struct InternalUserInfo *iui;
  324.   BOOL done;
  325.  
  326.   ObtainSemaphore(&UserSemaphore);
  327.   ObtainSemaphore(&GroupSemaphore);
  328.  
  329.   group = Open(muGroup_FileName,MODE_OLDFILE);
  330.   if(group) {
  331.     while(FGets(group,buff,BUFFLEN-1) && *buff != ' ' && *buff != '\n') {
  332.       s = nextsep(buff,'|');
  333.       if(*s != '|') break;
  334.       *(s++) = '\0';
  335.       gidstr = s;
  336.       s = nextsep(gidstr,'|');
  337.       if(*s != '|') break;
  338.       *s = '\0';
  339.  
  340.       if(StrToLong(gidstr,&gid) <= 0) break;
  341.  
  342.       if(!addgroup(buff,gid)) break;
  343.     }
  344.     while(FGets(group,buff,BUFFLEN-1)) { /* secondary groups */
  345.       s = nextsep(buff,':');
  346.       if(*s != ':') break;
  347.       *(s++) = '\0';
  348.       if(StrToLong(buff,&gid) <= 0) break;
  349.       igi = findgid(gid);
  350.       if(gid) {
  351.         do {
  352.           uidstr = s;
  353.           s = nextsep(uidstr,',');
  354.           done = (*s != ',');
  355.           *(s++) = '\0';
  356.           if(StrToLong(uidstr,&uid) <= 0) break;
  357.           iui = finduid(uid);
  358.           if(iui) {
  359.             if(!addsecgroup(iui,igi)) break;
  360.           }
  361.         } while(!done);
  362.       }
  363.     }
  364.     Close(group);
  365.   }
  366.   ReleaseSemaphore(&GroupSemaphore);
  367.   ReleaseSemaphore(&UserSemaphore);
  368. }
  369.  
  370. void __saveds guardian_func(void)
  371.  
  372. {
  373.   struct muBase *muBase;
  374.   struct NotifyRequest *passwd_req;
  375.   struct NotifyRequest *group_req;
  376.   BYTE passwd_sig,group_sig;
  377.   BPTR passwd_dir,olddir;  
  378.  
  379.   BOOL sok = FALSE,pok,gok;
  380.   struct Message *msg;
  381.   struct DosPacket *dp;
  382.   struct MsgPort *port;
  383.  
  384.   ULONG mask,rmask,pmask,gmask;
  385.  
  386.   port = &(((struct Process *)FindTask(0))->pr_MsgPort);
  387.   WaitPort(port);
  388.   msg = GetMsg(port);
  389.  
  390.   debug("Startup Message received !\n");
  391.  
  392.   if(msg == 0 || (dp = (struct DosPacket *)(msg->mn_Node.ln_Name)) == 0) {
  393.     Alert(AN_Unknown);
  394.     Wait(0); /* not much that I can do here */
  395.   }
  396.  
  397.   init_users();
  398.   init_groups();
  399.  
  400.   muBase = (struct muBase *)OpenLibrary(MULTIUSERNAME,MULTIUSERVERSION);
  401.  
  402.   if(muBase) {
  403.     passwd_dir = muGetPasswdDirLock();
  404.     CloseLibrary((struct Library *)muBase);
  405.   }
  406.   else {
  407.     UBYTE buff[256];
  408.  
  409.     if(GetVar("PASSWDDIR",buff,256,0) != -1) {
  410.       passwd_dir = Lock(buff,SHARED_LOCK);
  411.     }
  412.     else {
  413.       passwd_dir = Lock("S:",SHARED_LOCK);
  414.     }
  415.   }
  416.  
  417.   if(passwd_dir) {
  418.     debug("Passwd dir found !\n");
  419.     olddir = CurrentDir(passwd_dir);
  420.     passwd_sig = AllocSignal(-1);
  421.     if(passwd_sig != -1) {
  422.       group_sig = AllocSignal(-1);
  423.       if(group_sig != -1) {
  424.         debug("Signals allocated !\n");
  425.         passwd_req = (struct NotifyRequest *)
  426.           AllocMem(sizeof(struct NotifyRequest),MEMF_PUBLIC|MEMF_CLEAR);        
  427.         if(passwd_req) {
  428.           group_req = (struct NotifyRequest *)
  429.             AllocMem(sizeof(struct NotifyRequest),MEMF_PUBLIC|MEMF_CLEAR);        
  430.           if(group_req) {
  431.             debug("Notifiers allocated !\n");
  432.             passwd_req->nr_Name = muPasswd_FileName;
  433.             passwd_req->nr_Flags = NRF_SEND_SIGNAL;
  434.             passwd_req->nr_stuff.nr_Signal.nr_Task = FindTask(0);
  435.             passwd_req->nr_stuff.nr_Signal.nr_SignalNum = passwd_sig;
  436.  
  437.             group_req->nr_Name = muGroup_FileName;
  438.             group_req->nr_Flags = NRF_SEND_SIGNAL;
  439.             group_req->nr_stuff.nr_Signal.nr_Task = FindTask(0);
  440.             group_req->nr_stuff.nr_Signal.nr_SignalNum = group_sig;
  441.  
  442.             pok = StartNotify(passwd_req);
  443.             gok = StartNotify(group_req);
  444.  
  445.             read_users();
  446.             read_groups();
  447.  
  448.             sok = TRUE;
  449.             dp->dp_Res1 = DOSTRUE;
  450.             PutMsg(dp->dp_Port,msg); /* reply startup */
  451.  
  452.             pmask = 1L << passwd_sig;
  453.             gmask = 1L << group_sig;
  454.             mask = pmask | gmask | SIGBREAKF_CTRL_C;
  455.  
  456.             debug("Starting Loop !\n");
  457.  
  458.             for(;;) {
  459.               rmask = Wait(mask);
  460.  
  461.               if(rmask & SIGBREAKF_CTRL_C) break;
  462.               if(rmask & pmask) {
  463.                 debug("New Users !\n");
  464.                 ObtainSemaphore(&UserSemaphore);
  465.                 free_users();
  466.                 read_users();
  467.                 ReleaseSemaphore(&UserSemaphore);
  468.               }
  469.               if(rmask & gmask) {
  470.                 debug("New Groups !\n");
  471.                 ObtainSemaphore(&GroupSemaphore);
  472.                 free_groups();
  473.                 read_groups();
  474.                 ReleaseSemaphore(&GroupSemaphore);
  475.               }
  476.             }
  477.  
  478.             debug("Ending Loop !\n");
  479.  
  480.             if(gok) EndNotify(group_req);
  481.             if(pok) EndNotify(passwd_req);
  482.  
  483.             FreeMem(group_req,sizeof(struct NotifyRequest));
  484.           }
  485.           FreeMem(passwd_req,sizeof(struct NotifyRequest));
  486.         }
  487.         FreeSignal(group_sig);
  488.       }
  489.       FreeSignal(passwd_sig);
  490.     }
  491.     UnLock(CurrentDir(olddir));
  492.   }
  493.  
  494.   debug("Freeing Userinfo ...\n");
  495.   free_users();
  496.   debug("Freeing Groupinfo ...\n");
  497.   free_groups();
  498.  
  499.   if(!sok) {
  500.     dp->dp_Res1 = DOSFALSE;
  501.     dp->dp_Res2 = ERROR_NO_FREE_STORE;
  502.     PutMsg(dp->dp_Port,msg);
  503.   }
  504.  
  505.   debug("Ending Guardian !\n");
  506.  
  507.   Forbid();
  508.   guardian = 0;
  509. }
  510.  
  511. /* allocation functions */
  512.  
  513. struct UserInfo * __saveds LIBAllocUserInfo(void)
  514.  
  515. {
  516.   debug("AllocUserInfo\n");
  517.  
  518.   return((struct UserInfo *)AllocMem(sizeof(struct UserInfo),MEMF_CLEAR));
  519. }
  520.  
  521. struct GroupInfo * __saveds LIBAllocGroupInfo(void)
  522.  
  523. {
  524.   debug("AllocGroupInfo\n");
  525.  
  526.   return((struct GroupInfo *)AllocMem(sizeof(struct GroupInfo),MEMF_CLEAR));
  527. }
  528.  
  529. void __saveds __asm LIBFreeUserInfo(register __a0 struct UserInfo *user)
  530.  
  531. {
  532.   debug3("FreeUserInfo: Name: %s, UID: %ld\n",
  533.          user->ui_UserName,user->ui_UserID);
  534.  
  535.   FreeMem(user,sizeof(struct UserInfo));
  536. }
  537.  
  538.  
  539. void __saveds __asm LIBFreeGroupInfo(register __a0 struct GroupInfo *group)
  540.  
  541. {
  542.   debug3("FreeGroupInfo: Name: %s, GID: %ld\n",
  543.          group->gi_GroupName,group->gi_GroupID);
  544.  
  545.   FreeMem(group,sizeof(struct GroupInfo));
  546. }
  547.  
  548. /* xxxToyyy functions */
  549.  
  550. ULONG __saveds __asm LIBNameToUser(register __a0 STRPTR uname,
  551.                                    register __a1 struct UserInfo *user)
  552.  
  553. {
  554.   ULONG retval;
  555.   struct InternalUserInfo *iui;
  556.  
  557.   debug("NameToUser\n");
  558.  
  559.   ObtainSemaphoreShared(&UserSemaphore);
  560.  
  561. #ifdef NOBODY
  562.   if(stricmp(NOBODYNAME,uname) == 0) uname = NOBODYNAME; /* normalize */
  563. #endif
  564.  
  565.   iui = finduname(uname);
  566.  
  567.   if(iui) {
  568.     *user = iui->iui_UserInfo;
  569.     retval = 0;
  570.   }
  571.   else retval = ENVOYERR_UNKNOWNUSER;
  572.  
  573.   ReleaseSemaphore(&UserSemaphore);
  574.  
  575.   return(retval);
  576. }
  577.  
  578. ULONG __saveds __asm LIBNameToGroup(register __a0 STRPTR gname,
  579.                                     register __a1 struct GroupInfo *group)
  580.  
  581. {
  582.   ULONG retval;
  583.   struct InternalGroupInfo *igi;
  584.  
  585.   debug("NameToGroup\n");
  586.  
  587.   ObtainSemaphoreShared(&GroupSemaphore);
  588.  
  589.   igi = findgname(gname);
  590.  
  591.   if(igi) {
  592.     *group = igi->igi_GroupInfo;
  593.     retval = 0;
  594.   }
  595.   else retval = ENVOYERR_UNKNOWNGROUP;
  596.  
  597.   ReleaseSemaphore(&GroupSemaphore);
  598.  
  599.   return(retval);
  600. }
  601.  
  602. ULONG __saveds __asm LIBIDToUser(register __d0 UWORD uid, 
  603.                                  register __a0 struct UserInfo *user)
  604.  
  605. {
  606.   ULONG retval;
  607.   struct InternalUserInfo *iui;
  608.  
  609.   debug("IDToUser\n");
  610.  
  611.   ObtainSemaphoreShared(&UserSemaphore);
  612.  
  613.   iui = finduid(uid);
  614.  
  615.   if(iui) {
  616.     *user = iui->iui_UserInfo;
  617.     retval = 0;
  618.   }
  619.   else retval = ENVOYERR_UNKNOWNUSER;
  620.  
  621.   ReleaseSemaphore(&UserSemaphore);
  622.  
  623.   return(retval);
  624. }
  625.  
  626. ULONG __saveds __asm LIBIDToGroup(register __d0 UWORD gid,
  627.                                   register __a0 struct GroupInfo *group)
  628.  
  629. {
  630.   ULONG retval;
  631.   struct InternalGroupInfo *igi;
  632.  
  633.   debug("IDToGroup\n");
  634.  
  635.   ObtainSemaphoreShared(&GroupSemaphore);
  636.  
  637.   igi = findgid(gid);
  638.  
  639.   if(igi) {
  640.     *group = igi->igi_GroupInfo;
  641.     retval = 0;
  642.   }
  643.   else retval = ENVOYERR_UNKNOWNGROUP;
  644.  
  645.   ReleaseSemaphore(&GroupSemaphore);
  646.  
  647.   return(retval);
  648. }
  649.  
  650. /* Nextxxx functions */
  651.  
  652. ULONG __saveds __asm LIBNextUser(register __a0 struct UserInfo *user)
  653.  
  654. {
  655.   ULONG retval = ENVOYERR_LASTUSER;
  656.   struct InternalUserInfo *iui;
  657.  
  658.   debug("NextUser\n");
  659.  
  660.   ObtainSemaphoreShared(&UserSemaphore);
  661.  
  662.   if(user->ui_UserID != 0
  663. #ifdef NOBODY
  664.      || stricmp(user->ui_UserName,NOBODYNAME) == 0
  665. #endif
  666.     ) { /* take next */
  667.     iui = finduser(user->ui_UserName,user->ui_UserID);
  668.  
  669.     if(iui) iui = (struct InternalUserInfo *)(iui->iui_Node.mln_Succ);  
  670.     else retval = ENVOYERR_UNKNOWNUSER;
  671.   }
  672.   else { /* take first */   
  673.     iui = (struct InternalUserInfo *)(UserList.mlh_Head);  
  674.   }
  675.  
  676.   if(iui->iui_Node.mln_Succ) {
  677.     *user = iui->iui_UserInfo;
  678.     retval = 0;
  679.   }
  680.  
  681.   ReleaseSemaphore(&UserSemaphore);
  682.  
  683.   return(retval);
  684. }
  685.  
  686. ULONG __saveds __asm LIBNextGroup(register __a0 struct GroupInfo *group)
  687.  
  688. {
  689.   ULONG retval = ENVOYERR_LASTGROUP;
  690.   struct InternalGroupInfo *igi = 0;
  691.  
  692.   debug("NextGroup\n");
  693.  
  694.   ObtainSemaphoreShared(&GroupSemaphore);
  695.  
  696.   if(group->gi_GroupID != 0 || ((igi = findgid(0)) != 0 && 
  697.      strcmp(igi->igi_GroupInfo.gi_GroupName,group->gi_GroupName) == 0)) {
  698.  
  699.     if(igi == 0) igi = findgroup(group->gi_GroupName,group->gi_GroupID);
  700.  
  701.     if(igi) igi = (struct InternalGroupInfo *)(igi->igi_Node.mln_Succ);  
  702.     else retval = ENVOYERR_UNKNOWNGROUP;
  703.   }
  704.   else { /* take first */   
  705.     igi = (struct InternalGroupInfo *)(GroupList.mlh_Head);  
  706.   }
  707.  
  708.   if(igi->igi_Node.mln_Succ) {
  709.     *group = igi->igi_GroupInfo;
  710.     retval = 0;
  711.   }
  712.  
  713.   ReleaseSemaphore(&GroupSemaphore);
  714.  
  715.   return(retval);
  716. }
  717.  
  718. ULONG __saveds __asm LIBNextMember(register __a0 struct GroupInfo *group,
  719.                                    register __a1 struct UserInfo *user)
  720.  
  721. {
  722.   ULONG retval = ENVOYERR_LASTMEMBER;
  723.   struct InternalUserInfo *iui;
  724.   struct InternalGroupInfo *igi;
  725.  
  726.   debug("NextMember\n");
  727.  
  728.   ObtainSemaphoreShared(&UserSemaphore);
  729.   ObtainSemaphoreShared(&GroupSemaphore);
  730.  
  731.   if(group->gi_GroupID) {
  732.     igi = findgid(group->gi_GroupID);
  733.   }
  734.   else {
  735.     igi = findgname(group->gi_GroupName);
  736.     if(igi == 0) igi = findgid(0);
  737.   }
  738.   if(igi) {
  739.     *group = igi->igi_GroupInfo;
  740.  
  741.     if(user->ui_UserID != 0
  742. #ifdef NOBODY
  743.        || stricmp(user->ui_UserName,NOBODYNAME) == 0
  744. #endif
  745.       ) { /* takenext */
  746.  
  747.       iui = finduser(user->ui_UserName,user->ui_UserID);
  748.  
  749.       if(iui) iui = (struct InternalUserInfo *)(iui->iui_Node.mln_Succ);  
  750.       else retval = ENVOYERR_UNKNOWNUSER;
  751.     }
  752.     else { /* take first */   
  753.       iui = (struct InternalUserInfo *)(UserList.mlh_Head);  
  754.     }
  755.     
  756.     while(iui->iui_Node.mln_Succ) {
  757.       if(iui->iui_UserInfo.ui_PrimaryGroupID == group->gi_GroupID ||
  758.          issecmem(iui,igi)) break;
  759.       iui = (struct InternalUserInfo *)(iui->iui_Node.mln_Succ);  
  760.     }
  761.  
  762.     if(iui->iui_Node.mln_Succ) {
  763.       *user = iui->iui_UserInfo;
  764.       retval = 0;
  765.     }
  766.   }
  767.   else retval = ENVOYERR_UNKNOWNGROUP;
  768.     
  769.   ReleaseSemaphore(&GroupSemaphore);
  770.   ReleaseSemaphore(&UserSemaphore);
  771.  
  772.   return(retval);
  773. }
  774.  
  775. /* memberof */
  776.  
  777. ULONG __saveds __asm LIBMemberOf(register __a0 struct GroupInfo *group,
  778.                                  register __a1 struct UserInfo *user)
  779.  
  780. {
  781.   ULONG retval = ENVOYERR_UNKNOWNMEMBER;
  782.   struct InternalUserInfo *iui;
  783.   struct InternalGroupInfo *igi;
  784.  
  785.   debug("MemberOf\n");
  786.  
  787.   ObtainSemaphoreShared(&UserSemaphore);
  788.   ObtainSemaphoreShared(&GroupSemaphore);
  789.  
  790.   if(user->ui_UserID) {
  791.     iui = finduid(user->ui_UserID);
  792.   }
  793.   else {
  794.     iui = finduname(user->ui_UserName);
  795. #ifdef NOBODY
  796.     if(iui == 0) iui = finduid(0);
  797. #endif
  798.   }
  799.   if(iui) {
  800.     *user = iui->iui_UserInfo;
  801.  
  802.     if(group->gi_GroupID) {
  803.       igi = findgid(group->gi_GroupID);
  804.     }
  805.     else {
  806.       igi = findgname(group->gi_GroupName);
  807.       if(igi == 0) igi = findgid(0);
  808.     }
  809.     if(igi) {
  810.       *group = igi->igi_GroupInfo;
  811.       if(user->ui_PrimaryGroupID == group->gi_GroupID || issecmem(iui,igi)) {
  812.         retval = 0;
  813.       }
  814.     }
  815.     else retval = ENVOYERR_UNKNOWNGROUP;
  816.   }
  817.   else retval = ENVOYERR_UNKNOWNUSER;
  818.  
  819.   ReleaseSemaphore(&GroupSemaphore);
  820.   ReleaseSemaphore(&UserSemaphore);
  821.  
  822.   debug2("MemberOf-result: %ld\n",retval);
  823.  
  824.   return(retval);
  825. }
  826.  
  827. /* encryption & verification */
  828.  
  829. STRPTR __saveds __asm LIBECrypt(register __a0 STRPTR buff,
  830.                                 register __a1 STRPTR passwd,
  831.                                 register __a2 STRPTR uname)
  832.  
  833. {
  834.   debug3("ECrypt: Name: %s, Pwd: %s\n",uname,passwd); 
  835.  
  836.   return(ACrypt(buff,passwd,uname));
  837. }
  838.  
  839. ULONG __saveds __asm LIBVerifyUser(register __a0 STRPTR uname,
  840.                                    register __a1 STRPTR passwd,
  841.                                    register __a2 struct UserInfo *user)
  842.  
  843. {
  844.   UBYTE buff[16];
  845.  
  846.   debug3("VerifyUser: Name: %s, Pwd: %s\n",uname,passwd);
  847.  
  848.   if(ACrypt(buff,passwd,uname)) {
  849.     return(VerifyUserCrypt(uname,buff,user));
  850.   }
  851.   else {
  852.     return(ENVOYERR_NORESOURCES);
  853.   }
  854. }
  855.  
  856. ULONG __saveds __asm LIBVerifyUserCrypt(register __a0 STRPTR uname,
  857.                                         register __a1 STRPTR passwd,
  858.                                         register __a2 struct UserInfo *user)
  859.  
  860. {
  861.   ULONG retval = ENVOYERR_UNKNOWNUSER;
  862.   struct InternalUserInfo *iui;
  863.  
  864.   debug3("VerifyUserCrypt: Name: %s, Pwd: %s\n",uname,passwd);
  865.  
  866.   ObtainSemaphoreShared(&UserSemaphore);
  867.  
  868. #ifdef NOBODY
  869.   if(stricmp(NOBODYNAME,uname) == 0) uname = NOBODYNAME; /* normalize */
  870. #endif
  871.  
  872.   iui = finduname(uname);
  873.   if(iui && (iui->iui_CryptPasswd[0] == '\0' ||
  874.      strcmp(iui->iui_CryptPasswd,passwd) == 0)) {
  875.     *user = iui->iui_UserInfo;
  876.     retval = 0;
  877.   }
  878.  
  879.   ReleaseSemaphore(&UserSemaphore);
  880.  
  881.   debug2("VerifyUserCrypt: %ld\n",retval);
  882.  
  883.   return(retval);
  884. }
  885.